//
//  SEGAllDoorCollectionViewLayout.m
//  SEGUhomeIntelligentHardware
//
//  Created by Clavis on 2018/10/8.
//  Copyright © 2018 刘山. All rights reserved.
//

#import "SEGAllDoorCollectionViewLayout.h"
#import "SEGDoorCollViewCell.h"

typedef NS_ENUM(NSUInteger, SEGAllDoorDragDirection) {
    SEGAllDoorDragDirectionNone,
    SEGAllDoorDragDirectionLeft,
    SEGAllDoorDragDirectionRight,
    SEGAllDoorDragDirectionUp,
    SEGAllDoorDragDirectionDown
};

@interface SEGAllDoorCollectionViewLayout ()

@property (nonatomic, strong) NSIndexPath *originalIndexPath;
@property (nonatomic, strong) NSIndexPath *moveIndexPath;
@property (nonatomic, strong) UICollectionViewCell *originalCell;
@property (nonatomic, strong) UIView *tempMoveCell;
@property (nonatomic, assign) CGPoint originalCenter;
@property (nonatomic, assign) CGPoint lastPoint;
@property (nonatomic, strong) CADisplayLink *edgeTimer;
@property (nonatomic, assign) SEGAllDoorDragDirection dragScrollDirection;
@property (nonatomic, assign) BOOL isPanning;

@end

@implementation SEGAllDoorCollectionViewLayout

- (instancetype)init {
    self = [super init];
    if (self) {
        [self configureObserver];
    }
    return self;
}

- (void)dealloc {
    [self removeObserver:self forKeyPath:@"collectionView"];
    [self removeObserver:self forKeyPath:@"collectionView.contentOffset"];
}

- (void)configureObserver {
    [self addObserver:self forKeyPath:@"collectionView" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    
    if ([keyPath isEqualToString:@"collectionView"]) {
        [self setupGestureRecognizes];
    } else if ([keyPath isEqualToString:@"collectionView.contentOffset"]) {
        
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

- (void)setupGestureRecognizes {
    if (!self.collectionView) {
        return;
    }
    __weak typeof(self) weakself = self;
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithActionBlock:^(UILongPressGestureRecognizer * _Nonnull sender) {
        switch (sender.state) {
            case UIGestureRecognizerStateBegan:
                [weakself pressBegan:sender];
                break;
            case UIGestureRecognizerStateChanged:
                [weakself pressChange:sender];
                break;
            case UIGestureRecognizerStateEnded:
                [weakself pressCancel:sender];
                break;
            case UIGestureRecognizerStateCancelled:
                [weakself pressCancel:sender];
                break;
            default:
                [weakself pressCancel:sender];
                break;
        }
    }];
    longPress.minimumPressDuration = 0.2;
    [self.collectionView addGestureRecognizer:longPress];
}

- (void)pressBegan:(UILongPressGestureRecognizer *)longPress {
    CGPoint point = [longPress locationInView:self.collectionView];
    NSIndexPath *selectIndexPath = [self.collectionView indexPathForItemAtPoint:point];
    if (selectIndexPath) {
        _originalIndexPath = selectIndexPath;
        _isPanning = YES;
        UICollectionViewCell *targetCell = [self.collectionView cellForItemAtIndexPath:selectIndexPath];
        
        UIView *cellView = nil;
        if ([targetCell isKindOfClass:[SEGDoorCollViewCell class]]) {
            // 先给选中的cell添加高亮效果 截图 再取消高亮效果
            SEGDoorCollViewCell *doorCell = (SEGDoorCollViewCell *)targetCell;
            [doorCell updateSelectUI];
            cellView = [targetCell snapshotViewAfterScreenUpdates:YES];
            [doorCell resetSelectUI];
        } else {
            cellView = [targetCell snapshotViewAfterScreenUpdates:YES];
        }
        
        if (cellView) {
            targetCell.hidden = YES;
            _originalCell = targetCell;
            _originalCenter = targetCell.center;
            _tempMoveCell = cellView;
            _tempMoveCell.frame = cellView.frame;
            _tempMoveCell.center = targetCell.center;
            [self.collectionView addSubview:_tempMoveCell];
            [self setEdgeTimer];
            [self hideSelectCell];
        }
        
        // 通知cell开启动画
        [[NSNotificationCenter defaultCenter] postNotificationName:kSEGBeginDoorListShakeAnimationNotification object:selectIndexPath];
        
        // 通知代理
        if ([_delegate respondsToSelector:@selector(collectionViewDidBeginDrag)]) {
            [_delegate collectionViewDidBeginDrag];
        }
    }
}

- (void)pressChange:(UILongPressGestureRecognizer *)longPress {
    CGPoint point = [longPress locationInView:self.collectionView];
    _tempMoveCell.center = point;
    [self moveCell];
}

- (void)pressCancel:(UILongPressGestureRecognizer *)longPress {
    UICollectionViewCell *cell = [self.collectionView cellForItemAtIndexPath:_originalIndexPath];
    self.collectionView.userInteractionEnabled = NO;
    _isPanning = NO;
    [self stopEdgeTimer];
    
    [UIView animateWithDuration:0.25 animations:^{
        self.tempMoveCell.center = self.originalCenter;
    } completion:^(BOOL finished) {
        [self.tempMoveCell removeFromSuperview];
        cell.hidden = NO;
        self.originalCell.hidden = NO;
        self.collectionView.userInteractionEnabled = YES;
        self.originalIndexPath = nil;
        // 通知cell结束shake动画
        [[NSNotificationCenter defaultCenter] postNotificationName:kSEGEndDoorListShakeAnimationNotification object:nil];
    }];
    
    if ([_delegate respondsToSelector:@selector(collectionViewDidEndDragCell:)]) {
        [_delegate collectionViewDidEndDragCell:self.collectionView];
    }
}

/**
 隐藏选中的cell
 */
- (void)hideSelectCell {
    NSArray *visibleCells = [self.collectionView visibleCells];
    for (UICollectionViewCell *cell in visibleCells) {
        NSIndexPath *currentIndex = [self.collectionView indexPathForCell:cell];
        cell.hidden = _originalIndexPath != nil && _originalIndexPath.row == currentIndex.row;
    }
}

#pragma mark - handel scroll
- (void)setEdgeTimer {
    if (!_edgeTimer) {
        _edgeTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(edgeScroll)];
        [_edgeTimer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
    }
}

- (void)stopEdgeTimer {
    if (_edgeTimer) {
        [_edgeTimer invalidate];
        _edgeTimer = nil;
    }
}

- (void)edgeScroll {
    [self setScrollDirection];
    CGPoint originalOffset = self.collectionView.contentOffset;
    CGPoint tempMoveCellCenter = _tempMoveCell.center;
    CGFloat step = 6;
    BOOL needShake = YES;
    switch (_dragScrollDirection) {
        case SEGAllDoorDragDirectionLeft:
            [self.collectionView setContentOffset:CGPointMake(originalOffset.x - step, originalOffset.y) animated:NO];
            _tempMoveCell.center = CGPointMake(tempMoveCellCenter.x - step, tempMoveCellCenter.y);
            _lastPoint.x -= step;
            break;
        case SEGAllDoorDragDirectionRight:
            [self.collectionView setContentOffset:CGPointMake(originalOffset.x + step, originalOffset.y) animated:NO];
            _tempMoveCell.center = CGPointMake(tempMoveCellCenter.x + step, tempMoveCellCenter.y);
            _lastPoint.x += step;
            break;
        case SEGAllDoorDragDirectionUp:
            [self.collectionView setContentOffset:CGPointMake(originalOffset.x, originalOffset.y - step) animated:NO];
            _tempMoveCell.center = CGPointMake(tempMoveCellCenter.x, tempMoveCellCenter.y - step);
            _lastPoint.y -= step;
            break;
        case SEGAllDoorDragDirectionDown:
            [self.collectionView setContentOffset:CGPointMake(originalOffset.x, originalOffset.y + step) animated:NO];
            _tempMoveCell.center = CGPointMake(tempMoveCellCenter.x, tempMoveCellCenter.y + step);
            _lastPoint.y += step;
            break;
        default:
            needShake = NO;
            break;
    }
    if (needShake) {
        [self hideSelectCell];
    }
}

- (void)setScrollDirection {
    _dragScrollDirection = SEGAllDoorDragDirectionNone;
    
    if (!self.collectionView.isScrollEnabled) {
        return;
    }
    
    if (!_tempMoveCell || !self.collectionView) {
        return;
    }
    
    if (self.collectionView.bounds.size.height + self.collectionView.contentOffset.y - _tempMoveCell.center.y < _tempMoveCell.bounds.size.height / 2 && self.collectionView.bounds.size.height + self.collectionView.contentOffset.y < self.collectionView.contentSize.height) {
        _dragScrollDirection = SEGAllDoorDragDirectionDown;
    }
    
    if (_tempMoveCell.center.y - self.collectionView.contentOffset.y < _tempMoveCell.bounds.size.height / 2 && self.collectionView.contentOffset.y > 0) {
        _dragScrollDirection = SEGAllDoorDragDirectionUp;
    }
    
    if (self.collectionView.bounds.size.width + self.collectionView.contentOffset.x - _tempMoveCell.center.x < _tempMoveCell.bounds.size.width / 2 && self.collectionView.bounds.size.width + self.collectionView.contentOffset.x < self.collectionView.contentSize.width) {
        _dragScrollDirection = SEGAllDoorDragDirectionRight;
    }
    
    if (_tempMoveCell.center.x - self.collectionView.contentOffset.x < _tempMoveCell.bounds.size.width / 2 && self.collectionView.contentOffset.x > 0) {
        _dragScrollDirection = SEGAllDoorDragDirectionLeft;
    }
}

- (void)moveCell {
    if (!_tempMoveCell) {
        return;
    }
    for (UICollectionViewCell *cell in self.collectionView.visibleCells) {
        NSIndexPath *tempIndexPath = [self.collectionView indexPathForCell:cell];
        if (tempIndexPath == nil || tempIndexPath == _originalIndexPath) {
            continue;
        }
        CGFloat spacingX = fabs(_tempMoveCell.center.x - cell.center.x);
        CGFloat spacingY = fabs(_tempMoveCell.center.y - cell.center.y);
        if (spacingX <= _tempMoveCell.bounds.size.width/2.0 && spacingY <= _tempMoveCell.bounds.size.height/2.0) {
            _moveIndexPath = [self.collectionView indexPathForCell:cell];
            _originalCell = cell;
            _originalCenter = cell.center;
            // 更新数据源
            [self updateDataSource];
            [CATransaction begin];
            [self.collectionView moveItemAtIndexPath:_originalIndexPath toIndexPath:_moveIndexPath];
            [CATransaction commit];
            // 通知代理
            // 设置移动之后的起始indexPath
            _originalIndexPath = _moveIndexPath;
            break;
        }
    }
}

- (void)updateDataSource {
    NSMutableArray *tempDataSource = [[NSMutableArray alloc] init];
    if ([_delegate respondsToSelector:@selector(collectionViewDataSourceArray:)] && _moveIndexPath != nil && _originalIndexPath != nil) {
        [tempDataSource addObjectsFromArray:[_delegate collectionViewDataSourceArray:self.collectionView]];
        
        id object = [tempDataSource objectAtIndex:_originalIndexPath.row];
        [tempDataSource removeObjectAtIndex:_originalIndexPath.row];
        [tempDataSource insertObject:object atIndex:_moveIndexPath.row];
        
        // 将排序好的数据传递给外部
        if ([_delegate respondsToSelector:@selector(collectionView:didDragCellWithNewData:)]) {
            [_delegate collectionView:self.collectionView didDragCellWithNewData:tempDataSource];
        }
    }
}

@end
